package org.sgmiller.quickstem;

import static org.sgmiller.quickstem.TransactionState.*;

class SerializableTransaction extends Transaction {

	SerializableTransaction() {
		super(IsolationLevel.SERIALIZABLE, true);
	}

	public SerializableTransaction(long nestedTid) {
		super(IsolationLevel.SERIALIZABLE, nestedTid, true);
	}

	ConcurrentHashSet<Transaction> dependentTransactions=
		new ConcurrentHashSet<Transaction>(1);


	void doCommit() {
		for (Transaction txn: dependentTransactions) {
			while (txn.state==TransactionState.OPEN) {
				synchronized(txn) {
					if (txn.state==TransactionState.OPEN) {
						try {
							txn.wait();
						} catch (InterruptedException e) {
						}
					}
				}
			}
			
			if (txn.state == COMMITTED) {
				String msg="Could not commit, serialization conflict between "+this+" and "+txn+".  Transaction rolled back.";
				irollback();
				throw new SerializationException(msg);
			}
		}
	}

	@Override
	protected Object consider(Stem<?> stem, Version<?> v) {
		if (v.txn.isTopLevel() || isSubtransaction(v.txn)) {
			switch(v.txn.state.ordinal) {
			case ORD_OPEN:
				if (isTopLevel() && v.txn.tid <= tid) {
					//hmm, this may commit, invalidating our result
					dependentTransactions.add(v.txn);
				}
				if (v.txn.parentTid != parentTid) 
					break;
			case ORD_COMMITTED:
				return v.value;
			}
		} 
		return VAL_CONTINUE;
	}
}
